#include "Room.h"
#include <iostream>
//This code defines a `Room` class for a game, managing room attributes like name, description, type (healing, damaging, treasure, etc.), and exits. It generates random items (weapons, armor, amulets) with varying stats. The destructor cleans up items and enemies to prevent memory leaks. Methods handle adding/removing items/enemies, setting exits, and applying room effects (healing, damaging, or spawning items in treasure rooms). The `[]` operator is overloaded to access exits by direction.
// Implementation of random item generator
Item* Room::generateRandomItem() {
    static std::random_device rd;
    static std::mt19937 gen(rd());
    
    // Randomly select item type
    std::uniform_int_distribution<> typeRoll(0, 2);
    int itemType = typeRoll(gen);
    
    // Random attribute values
    std::uniform_int_distribution<> valueRoll(1, 5);
    
    // Generate different items based on type
    switch (itemType) {
        case 0: // Generate weapon (mainly increases attack)
            return new Item(
                "Random Weapon",
                "A randomly generated weapon, glowing softly",
                valueRoll(gen),                  // Small health bonus
                valueRoll(gen) + valueRoll(gen), // More attack
                valueRoll(gen) / 2               // Very little defense
            );
        case 1: // Generate armor (mainly increases defense)
            return new Item(
                "Random Armor",
                "A randomly generated armor, looks sturdy",
                valueRoll(gen),                  // Small health bonus
                valueRoll(gen) / 2,              // Very little attack
                valueRoll(gen) + valueRoll(gen)  // More defense
            );
        case 2: // Generate amulet (mainly increases health)
            return new Item(
                "Random Amulet",
                "A randomly generated amulet, emanating mysterious energy",
                valueRoll(gen) + valueRoll(gen) + valueRoll(gen), // Large health bonus
                valueRoll(gen) / 2,                               // Very little attack
                valueRoll(gen) / 2                                // Very little defense
            );
        default:
            return new Item("Random Item", "A common random item", 1, 1, 1);
    }
}

Room::Room(const std::string& _name, const std::string& _desc, RoomType _type, int _effect)
    : name(_name), description(_desc), type(_type), roomEffect(_effect) {
}

Room::~Room() {
    // Release memory for all items
    for (Item* item : items) {
        delete item;
    }
    items.clear();
    
    // Release memory for all enemies
    for (Enemy* enemy : enemies) {
        delete enemy;
    }
    enemies.clear();
    
    // Exit pointers don't need to be deleted here, Game class is responsible
    exits.clear();
}

std::string Room::getName() const {
    return name;
}

std::string Room::getDescription() const {
    return description;
}

RoomType Room::getType() const {
    return type;
}

int Room::getRoomEffect() const {
    return roomEffect;
}

void Room::addItem(Item* item) {
    if (item) {
        items.push_back(item);
    }
}

void Room::addRandomItem() {
    Item* randomItem = generateRandomItem();
    addItem(randomItem);
}

Item* Room::takeItem(size_t index) {
    if (index < items.size()) {
        Item* item = items[index];
        items.erase(items.begin() + index);
        return item;
    }
    return nullptr;
}

const std::vector<Item*>& Room::getItems() const {
    return items;
}

void Room::addEnemy(Enemy* enemy) {
    if (enemy) {
        enemies.push_back(enemy);
    }
}

void Room::removeEnemy(size_t index) {
    if (index < enemies.size()) {
        delete enemies[index];
        enemies.erase(enemies.begin() + index);
    }
}

const std::vector<Enemy*>& Room::getEnemies() const {
    return enemies;
}

void Room::setExit(const std::string& direction, Room* room) {
    if (room) {
        exits[direction] = room;
    }
}

Room* Room::getExit(const std::string& direction) const {
    auto it = exits.find(direction);
    if (it != exits.end()) {
        return it->second;
    }
    return nullptr;
}

std::map<std::string, Room*> Room::getExits() const {
    return exits;
}

int Room::applyRoomEffect(ICharacter& character) {
    // Pre-declare all variables
    static std::random_device rd;
    static std::mt19937 gen(rd());
    std::uniform_real_distribution<> dis(0.0, 1.0);
    
    switch (type) {
        case RoomType::HEALING:
            // Healing rooms restore health
            if (character.isAlive()) {
                std::cout << "This room radiates healing light, you feel some health being restored." << std::endl;
                // Create temporary healing item
                Item* healEffect = new Item("Healing Energy", "Room's healing effect", roomEffect, 0, 0);
                character.addToInventory(healEffect);
                return roomEffect; // Return the amount restored
            }
            break;
            
        case RoomType::DAMAGING:
            // Damage rooms cause harm
            if (character.isAlive()) {
                std::cout << "This room is filled with harmful gas, you feel uncomfortable." << std::endl;
                character.takeDamage(roomEffect);
                std::cout << "You lost " << roomEffect << " health points!" << std::endl;
                return -roomEffect; // Return negative value to indicate damage
            }
            break;
            
        case RoomType::TREASURE:
            // Treasure rooms have a chance to discover random items
            if (dis(gen) < 0.3) { // 30% chance to find a random item
                std::cout << "You found a hidden item in the treasure room!" << std::endl;
                addRandomItem();
                return 1; // Indicates an item was found
            }
            break;
            
        default:
            // Normal rooms have no special effects
            break;
    }
    
    return 0;
}

void Room::displayRoom() const {
    std::cout << "=== " << name << " ===" << std::endl;
    std::cout << description << std::endl << std::endl;
    
    // Display room type
    switch (type) {
        case RoomType::HEALING:
            std::cout << "[Healing Room] Staying here can restore health." << std::endl;
            break;
        case RoomType::DAMAGING:
            std::cout << "[Dangerous Room] Staying here will cause damage." << std::endl;
            break;
        case RoomType::TREASURE:
            std::cout << "[Treasure Room] Valuable items might be hidden here." << std::endl;
            break;
        default:
            // Normal rooms don't display special messages
            break;
    }
    
    // Display items in the room
    if (!items.empty()) {
        std::cout << "Items here: ";
        for (size_t i = 0; i < items.size(); ++i) {
            std::cout << items[i]->name;
            if (i < items.size() - 1) {
                std::cout << ", ";
            }
        }
        std::cout << std::endl;
    } else {
        std::cout << "No items here." << std::endl;
    }
    
    // Display enemies in the room
    if (!enemies.empty()) {
        std::cout << "Enemies here: ";
        for (size_t i = 0; i < enemies.size(); ++i) {
            std::cout << enemies[i]->toString();
            if (i < enemies.size() - 1) {
                std::cout << ", ";
            }
        }
        std::cout << std::endl;
    } else {
        std::cout << "No enemies here." << std::endl;
    }
    
    // Display available exits
    if (!exits.empty()) {
        std::cout << "Available exits: ";
        size_t i = 0;
        for (const auto& exit : exits) {
            std::cout << exit.first;
            if (i < exits.size() - 1) {
                std::cout << ", ";
            }
            ++i;
        }
        std::cout << std::endl;
    } else {
        std::cout << "No exits here." << std::endl;
    }
    
    std::cout << std::endl;
}

Room* Room::operator[](const std::string& direction) {
    // Use [] operator to access adjacent rooms
    return getExit(direction);
} 